home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
027a
/
onotes.zip
/
TBMANY.PRG
< prev
next >
Wrap
Text File
|
1991-04-19
|
16KB
|
326 lines
*╔══════════════════════════════════════════════════════════════════╗*
*║ Module Name: TBSIMPLE.PRG ║*
*║ Description: A bare bones 'one to many' TBrowse system. ║*
*║ Notes......: COMPILE with the /n/w switch. ║*
*║ Author.....: Micheal Todd Charron ║*
*║ Date.......: April 29, 1991 ║*
*║ History....: Lee Dimambro asked me to write a bare bones ║*
*║ 'one to many' TBrowse system from scratch. 30 ║*
*║ minutes from start to finish. It could have ║*
*║ been faster if I hadn't been using WP 5.1 as ║*
*║ the program editor. This program is similiar ║*
*║ but with less frills. Thanks Lee. ║*
*║ ║*
*║ Copyright..: (c) The people at Nantucket Canada, 1991 ║*
*╚══════════════════════════════════════════════════════════════════╝*
#include "inkey.ch"
FUNCTION Main()
LOCAL nI, nKey
LOCAL oBrowse := TBROWSEDB( 1, 2, 22, 78 )
USE MANY INDEX MANY NEW
USE ONE NEW
SET RELATION TO ONE->Group INTO MANY
CLS
@0, 1 TO 23, 79 DOUBLE
oBrowse:HEADSEP := '═╤═'
oBrowse:COLSEP := ' │ '
FOR nI := 1 TO FCOUNT()
oBrowse:ADDCOLUMN( TBCOLUMNNEW( FIELD( nI ),;
FIELDBLOCK( FIELD( nI ) ) ) )
NEXT nI
DO WHILE .T.
DO WHILE ! ( oBrowse:STABILIZE() )
ENDDO
nKey := INKEY( 0 )
DO CASE
CASE nKey == K_ENTER
MANY->( ManyBrowse( ONE->Group ) )
CASE nKey == K_DOWN
oBrowse:DOWN()
CASE nKey == K_UP
oBrowse:UP()
CASE nKey == K_PGDN
oBrowse:PAGEDOWN()
CASE nKey == K_PGUP
oBrowse:PAGEUP()
CASE nKey == K_RIGHT
oBrowse:RIGHT()
CASE nKey == K_LEFT
oBrowse:LEFT()
CASE nKey == K_ESC
EXIT
ENDCASE
ENDDO
RETURN Nil
* * * *
*
* Function ManyBrowse()
*
FUNCTION ManyBrowse( xKey )
LOCAL nI, nKey
LOCAL oBrowse := TBROWSENEW( 9, 40, 21, 77 )
SAVE SCREEN
@8, 39 TO 22, 78 DOUBLE
oBrowse:HEADSEP := '═╤═'
oBrowse:COLSEP := ' │ '
oBrowse:SKIPBLOCK :=;
{ | nMove | SkipKey( nMove, xKey ) }
FOR nI := 1 TO FCOUNT()
oBrowse:ADDCOLUMN( TBCOLUMNNEW( FIELD( nI ),;
FIELDBLOCK( FIELD( nI ) ) ) )
NEXT nI
DO WHILE .T.
DO WHILE ! ( oBrowse:STABILIZE() )
ENDDO
nKey := INKEY( 0 )
DO CASE
CASE nKey == K_DOWN
oBrowse:DOWN()
CASE nKey == K_UP
oBrowse:UP()
CASE nKey == K_PGDN
oBrowse:PAGEDOWN()
CASE nKey == K_PGUP
oBrowse:PAGEUP()
CASE nKey == K_RIGHT
oBrowse:RIGHT()
CASE nKey == K_LEFT
oBrowse:LEFT()
CASE nKey == K_ESC
EXIT
ENDCASE
ENDDO
RESTORE SCREEN
RETURN Nil
* * * *
*
* Function SkipKey()
*
FUNCTION SkipKey( nMove, xKey )
LOCAL nI, nMovement := 0
IF nMove > 0
FOR nI := 1 TO nMove
SKIP 1
IF xKey != UPPER( MANY->Group )
SKIP -1
EXIT
ENDIF
nMovement++
NEXT nI
ELSEIF nMove < 0
FOR nI := 1 TO -( nMove )
SKIP -1
IF xKey != UPPER( MANY->Group ) .OR. BOF()
IF ! BOF()
SKIP 1
ENDIF
EXIT
ENDIF
nMovement--
NEXT nI
ENDIF
RETURN nMovement
/*****************************************************************************
FUNCTION Main()
******************************************************************************
I will assume that you have already looked through TBSIMPLE.PRG and do not
need an explanation of simpler aspects of the TBrowse.
╒════════════════════════════════════════════════════════════════════╕
Line 22 │ USE MANY INDEX MANY NEW │
Line 23 │ USE ONE NEW │
Line 24 │ SET RELATION TO ONE->Group INTO MANY │
╘════════════════════════════════════════════════════════════════════╛
Opens the 'MANY' database which holds multiple records for every record in
the 'ONE' database. Also on the same line the 'MANY' index is opened. This
index has the key of UPPER( GROUP ). Then the 'ONE' database is opened which
then becomes the active database. Take note that the 'NEW' clause in the
'USE' command will automatically selects the next available workarea. Then,
finally, the relation from the 'ONE' database into the 'MANY' database is set.
╒════════════════════════════════════════════════════════════════════╕
Line 29 │ @0, 1 TO 23, 79 DOUBLE │
Line 30 │ oBrowse:HEADSEP := '═╤═' │
Line 31 │ oBrowse:COLSEP := ' │ ' │
╘════════════════════════════════════════════════════════════════════╛
Fluff, pure fluff. I take the luxury of adding a double line box around the
main TBrowse and providing heading and column separators for the TBrowse.
╒════════════════════════════════════════════════════════════════════╕
Line 44 │ CASE nKey == K_ENTER │
Line 45 │ MANY->( ManyBrowse( ONE->Group ) ) │
╘════════════════════════════════════════════════════════════════════╛
Calls ManyBrowse() and passes the current value of the relation's key
expression.
'MANY->( )' is a neat trick which will automatically make the 'MANY' workarea
the current workarea when the function between the paranthesis is executed.
But the really great aspect of this is that you are automatically returned to
the workarea that was active before the function call. Even if you select
other workareas in the function you call, you are returned to the workarea
that was active before the function call. Use it, its helpful.
******************************************************************************
FUNCTION ManyBrowse()
******************************************************************************
╒════════════════════════════════════════════════════════════════════╕
Line 73 │ LOCAL oBrowse := TBROWSENEW( 9, 40, 21, 77 ) │
╘════════════════════════════════════════════════════════════════════╛
The 'MANY' TBrowse object is created and it's reference is assigned to the
variable "oBrowse". The variable "oBrowse" in this function and the variable
"oBrowse" in the Main() function are not the same variable, remember that. By
declaring them LOCAL they only share the same name. They are only visible to
the functions that they are declared in.
In Clipper 5.0 there are two ways to create a TBrowse object. The first way
is to use the function TBROWSEDB() and the second way is to use the function
TBROWSENEW(). TBROWSEDB() creates the TBrowse object with a predefined
mechanism for moving from the top to the bottom of a database. The mechanism
is stored in object in the instance variable 'SKIPBLOCK'. With TBROWSENEW(),
the object is created without a mechanism. The instance variable 'SKIPBLOCK'
is empty.
For the 'MANY' TBrowse the mechanism for moving through the database must be
defined in order to assure that the TBrowse will only display the data that
corresponds to the related record in the 'ONE' TBrowse.
╒════════════════════════════════════════════════════════════════════╕
Line 75 │ SAVE SCREEN │
╘════════════════════════════════════════════════════════════════════╛
The screen is saved so that the main TBrowse screen can be returned to without
disturbing its contents.
╒════════════════════════════════════════════════════════════════════╕
Line 81 │ oBrowse:SKIPBLOCK :=; │
Line 82 │ { | nMove | SkipKey( nMove, xKey ) } │
╘════════════════════════════════════════════════════════════════════╛
The mechanism for moving through the 'MANY' database is created and stored in
the instance variable SKIPBLOCK. When the TBrowse starts to display the data
it will evaluate this code block which is stored in its SKIPBLOCK instance
variable.
Please remember that nothing is being executed at this point. The code block
is only being stored for later use.
╒════════════════════════════════════════════════════════════════════╕
Line 90 │ DO WHILE ! ( oBrowse:STABILIZE() ) │
Line 91 │ ENDDO │
╘════════════════════════════════════════════════════════════════════╛
When this loop is encountered, it will check for any data rows that have been
changed and loop through until they are updated. If the TBrowse must find
data that it has not already found, it will evaluate the code block stored in
the instance variable SKIPBLOCK and pass into the code block the number of
rows it must move to display that data.
╒═══════════════════════════════════════════════════════════════════╕
Line 108 │ CASE nKey == K_ESC │
Line 109 │ EXIT │
╘═══════════════════════════════════════════════════════════════════╛
Exits out of the DO WHILE loop and returns to the main TBrowse.
╒═══════════════════════════════════════════════════════════════════╕
Line 114 │ RESTORE SCREEN │
╘═══════════════════════════════════════════════════════════════════╛
Restores the main TBrowse screen.
******************************************************************************
FUNCTION SkipKey()
******************************************************************************
╒═══════════════════════════════════════════════════════════════════╕
Line 124 │ FUNCTION SkipKey( nMove, xKey ) │
╘═══════════════════════════════════════════════════════════════════╛
The variable "nMove" contains the number of rows the TBrowse has requested to
move. The variable "xKey" contains the value of the key field in the 'ONE'
database.
╒═══════════════════════════════════════════════════════════════════╕
Line 125 │ LOCAL nI, nMovement := 0 │
╘═══════════════════════════════════════════════════════════════════╛
The variable "nI" is for the FOR ... NEXT loop and the "nMovement" variable
will hold the value that the SkipKey() function will return.
╒═══════════════════════════════════════════════════════════════════╕
Line 127 │ IF nMove > 0 │
Line 128 │ FOR nI := 1 TO nMove │
Line 129 │ SKIP 1 │
Line 130 │ IF xKey != UPPER( MANY->Group ) │
Line 131 │ SKIP -1 │
Line 132 │ EXIT │
Line 133 │ ENDIF │
Line 134 │ nMovement++ │
Line 135 │ NEXT nI │
╘═══════════════════════════════════════════════════════════════════╛
If the TBrowse has requested to move down more than one row, this code is
executed. The FOR...NEXT loops from 1 to the value of "nMove" or until the
EXIT command is issued.
On line 129 we SKIP to the next record.
On line 130 we check to see if UPPER( MANY->Group ) is different from the
value of xkey.
If the value of UPPER( MANY->Group ) is different from the value of xkey, we
have gone too far and must move back one record and exit the FOR...NEXT loop.
Lines 131 and 132 respectively.
On line 134 the variable "nMovement" is incremented by one. Therefore,
nMovement is incremented by one for every successful loop of the FOR...NEXT
loop.
╒═══════════════════════════════════════════════════════════════════╕
Line 137 │ ELSEIF nMove < 0 │
Line 138 │ FOR nI := 1 TO -( nMove ) │
Line 139 │ SKIP -1 │
Line 140 │ IF xKey != UPPER( MANY->Group ) .OR. BOF() │
Line 141 │ IF ! BOF() │
Line 142 │ SKIP 1 │
Line 143 │ ENDIF │
Line 144 │ EXIT │
Line 145 │ ENDIF │
Line 146 │ nMovement-- │
Line 147 │ NEXT nI │
╘═══════════════════════════════════════════════════════════════════╛
This section is much like the previous section. The only difference is that
the section checks for backward movement through the database and that it also
checks to see if while skipping backwards, the beginning of the file is hit.
╒═══════════════════════════════════════════════════════════════════╕
Line 149 │ RETURN nMovement │
╘═══════════════════════════════════════════════════════════════════╛
Returns the amount of rows the TBrowse can move.
******************************************************************************/
** Please remember that this is not the only way to make one of these **
** applications. It is only the simplest way I can think of showing **
** how this can be done. **
*******************************************************************************